; enums
(define-constant *E-StatementType-symbol*     0x01)
(define-constant *E-StatementType-argument*   0x02)
(define-constant *E-StatementType-loop*       0x03)
(define-constant *E-StatementType-optional*   0x04)

; messages
(define-constant *M-Statement-make-symbol*    0x01)
(define-constant *M-Statement-make-argument*  0x02)
(define-constant *M-Statement-make-loop*      0x03)
(define-constant *M-Statement-is-symbol*      0x04)
(define-constant *M-Statement-is-argument*    0x05)

; make-Statement todo
(define (make-Statement self symbol type children)
	(define is-symbol? (lambda () (eqv type *E-StatementType-symbol*)))
	(define is-argument? (lambda () (eqv type *E-StatementType-argument*)))
	(lambda (message)
		(case message
			((*M-Statement-make-symbol*)
				(lambda (s)
					(begin (set! symbol s)
						(set! type *E-StatementType-symbol*)
						(set! children *nil*)
						self)))
			((*M-Statement-make-argument*)
				(lambda ()
					(begin (set! symbol *nil*)
						(set! type *E-StatementType-argument*)
						(set! children (create-Queue *nil* *nil*))
						self)))
			((*M-Statement-make-loop*)
				(lambda ()
					(begin (set! symbol *nil*)
						(set! type *E-StatementType-loop*)
						(set! children (create-Queue *nil* *nil*))
						self)))
			((*M-Statement-is-symbol*) is-symbol?)
			((*M-Statement-is-argument*) is-argument?)
			; todo
			(else ()))))

; match-statement
(define (match-statement st1 st2)
	(let ((s1 (ask st1 *M-Statement-symbol*)) (s2 (ask st2 *M-Statement-symbol*)))
		(cond
			((and (statement-symbol? s1) (statement-symbol? s2) (eq s1 s2)) *true*)
			((and (statement-argument? s1) (statement-argument? s2)) *true*)
			(else *false*))))

